﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
using SalaryReport.Core.Events;

namespace SalaryReport.Core.Excel
{
    public class ExcelFile : INotify
    {
        private const string ERROR_TEXT = "ERROR";
        private readonly Workbook workBook;
        private readonly string fileName;
        private Worksheet workSheet;
        private Range range;

        public object[,] Values { get; private set; }

        public int SheetsCount { get; set; }
        
        public ExcelFile(string fileName)
        {
            var app = new Application();

            this.fileName = fileName;
            this.workBook = app.Workbooks.Open(fileName, 0, true, 5, string.Empty, string.Empty, true,
                                          XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);

            SheetsCount = workBook.Sheets.Count;
        }

        public void Init(int sheetIndex)
        {
            this.workSheet = (Worksheet)workBook.Sheets[sheetIndex];
            this.range = workSheet.UsedRange;

            Values = (object[,])range.Value[XlRangeValueDataType.xlRangeValueDefault];

            this.workBook.Close(false, this.fileName, null);
            Marshal.ReleaseComObject(this.workBook);
        }

        public List<ExcelData> GetValuesForSettings(ExcelSettings settings, int index)
        {
            var result = new List<ExcelData>();

            try
            {
                var row = Values.GetRow(index);

                foreach (var item in settings.Items)
                {
                    var data = new ExcelData();

                    if (item is ExcelColumn)
                    {
                        var column = item as ExcelColumn;
                        var num = (int)column.Column;
                        data.Name = item.Name;
                        data.NameTemplate = item.TemplateName;
                        if (num >= 0 && num < row.Length)
                        {
                            data.Value = row[num] == null
                                             ? ERROR_TEXT
                                             : row[(int)column.Column].ToString();
                        }
                        else
                        {
                            data.Value = ERROR_TEXT;
                        }

                        result.Add(data);
                    }
                    else if (item is ExcelCell)
                    {
                        var cell = item as ExcelCell;
                        data.Name = item.Name;
                        data.NameTemplate = item.TemplateName;
                        data.Value = Values[cell.Row, (int)cell.Column + 1] == null
                                         ? ERROR_TEXT
                                         : Values[cell.Row, (int)cell.Column + 1].ToString();
                        
                        result.Add(data);
                    }
                }
            }
            catch (Exception ex)
            {
                Notify(new SalaryArgs(string.Format("Excel parsing error! Error text: {0}.", ex.Message)));
            }

            return result;
        }
        
        public event EventHandler<SalaryArgs> OnNotify;

        private void Notify(SalaryArgs args)
        {
            if (OnNotify != null)
            {
                OnNotify(this, args);
            }
        }
    }
}